#include <learn/check_gl.h>
#include <learn/gl/gl_callback.h>

#include <algorithm>
#include <array>
#include <iostream>
#include <numeric>
#include <random>
#include <vector>

using namespace xi::gl;

GLfloat mixed[] = {-0.5, -0.5, 0.0, 1, 0, 0, 0.5, 0.0, 0.0, 0, 1, 0, 0.0, 0.5, 0.0, 0, 0, 1};

void init()
{
    glEnable(GL_DEPTH_TEST);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    // 附加掩模
    glEnable(GL_POLYGON_STIPPLE);
    GLubyte fillPartten[] = {0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
                             0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
                             0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
                             0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
                             0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
                             0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
                             0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
                             0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
                             0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00};
    glPolygonStipple(fillPartten);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);

    glVertexPointer(3, GL_FLOAT, 6 * sizeof(GLfloat), &mixed[0]);
    glColorPointer(3, GL_FLOAT, 6 * sizeof(GLfloat), &mixed[3]);
}

void arrow()
{
    GLubyte bitShape[] = {0x1c, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x1c, 0x00,
                          0xff, 0x80, 0x7f, 0x00, 0x3e, 0x00, 0x1c, 0x00, 0x08, 0x00};

    // 在 (0,0) 位置输出位图，位图阵列有 9 列 10 行
    glRasterPos2i(0, 0);
    glBitmap(9, 10, 0, 0, 20, 15, bitShape);
}

void random_color()
{
    std::vector<GLfloat> bitShapeFloat(100 * 100 * 3);
    std::generate(bitShapeFloat.begin(), bitShapeFloat.end(), [gen = std::mt19937(std::random_device{}())]() mutable {
        std::uniform_real_distribution<float> dis(0.0f, 1.0f);
        return dis(gen);
    });

    glRasterPos2i(0, 0);
    glDrawPixels(100, 100, GL_RGB, GL_FLOAT, bitShapeFloat.data());
}

void triangle()
{
    int ind[] = {0, 1, 2};
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, ind);
}

void render()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // 指定位图储存模式，参数 1 表示数据用字节边界对齐
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    arrow();
    random_color();
    triangle();
}

int main()
{
    if (!glfwInit())
    {
        std::cerr << "Failed to initialize GLFW" << std::endl;
        return -1;
    }

    GLFWwindow *window = glfwCreateWindow(800, 600, "Three Stars", nullptr, nullptr);
    if (!window)
    {
        std::cerr << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    // 注册函数
    glfwSetFramebufferSizeCallback(window, GLFWWindowResize);
    glfwSetScrollCallback(window, GLFWScrollCallback);
    glfwSetMouseButtonCallback(window, GLFWMouseButtonCallback);
    glfwSetCursorPosCallback(window, GLFWCursorPosCallback);
    glfwSetKeyCallback(window, GLFWKeyCallback);
    glfwSetDropCallback(window, GLFWDropCallback);

    init();
    while (!glfwWindowShouldClose(window))
    {
        // 视图变换
        transform(window);

        render();
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glfwTerminate();

    return 0;
}
